
mod ball;

use ggez::graphics::StrokeOptions;
use ggez::{Context, GameResult, GameError, graphics};
use ggez::mint::Point2;
use glam::{Vec2, Vec3};

const UX: Vec2 = Vec2{x: -0.9, y: 0.25};
const UY: Vec2 = Vec2{x: 0.9, y: 0.25};
const UZ: Vec2 = Vec2{x: 0.0, y: -1.0};
const ZERO_PIVOT: Vec2 = Vec2{x:400.0, y: 400.0};
pub struct State{
    ball: ball::Ball,
}

impl State{
    pub fn new() -> State {
        State{ball: ball::Ball::new()}
    }
}

impl ggez::event::EventHandler<GameError> for State {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        self.ball.step();
        Ok(())
    }
    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        let mut canvas = graphics::Canvas::from_frame(ctx, graphics::Color::WHITE);
        let location: Vec3 = self.ball.get_location();
        

        let rect1 = graphics::Mesh::new_polygon(
            ctx,
            graphics::DrawMode::fill(),
            &[
                vec_to_render(&Vec3::new(0.0, 0.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 0.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 300.0, 0.0)),
                vec_to_render(&Vec3::new(0.0, 300.0, 0.0)),
            ],
            graphics::Color::new(0.8, 0.8, 0.8, 1.0),
        )?;
        canvas.draw(&rect1, graphics::DrawParam::default());
        let rect1 = graphics::Mesh::new_polygon(
            ctx,
            graphics::DrawMode::fill(),
            &[
                vec_to_render(&Vec3::new(0.0, 0.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 0.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 0.0, 300.0)),
                vec_to_render(&Vec3::new(0.0, 0.0, 300.0)),
            ],
            graphics::Color::new(0.9, 0.9, 0.9, 1.0),
        )?;
        canvas.draw(&rect1, graphics::DrawParam::default());
        let rect1 = graphics::Mesh::new_polygon(
            ctx,
            graphics::DrawMode::fill(),
            &[
                vec_to_render(&Vec3::new(0.0, 0.0, 0.0)),
                vec_to_render(&Vec3::new(0.0, 300.0, 0.0)),
                vec_to_render(&Vec3::new(0.0, 300.0, 300.0)),
                vec_to_render(&Vec3::new(0.0, 0.0, 300.0)),
            ],
            graphics::Color::new(0.85, 0.85, 0.85, 1.0),
        )?;
        canvas.draw(&rect1, graphics::DrawParam::default());


        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::fill(),
            vec_to_render(&location),
            16.0,
            0.1,
            graphics::Color::new(0.5, 0.5, 0.5, 1.0),
        )?;
        canvas.draw(&circle, graphics::DrawParam::default());
        let circle = graphics::Mesh::new_circle(
            ctx,
            graphics::DrawMode::Stroke(StrokeOptions::DEFAULT),
            vec_to_render(&location),
            16.0,
            0.1,
            graphics::Color::BLACK,
        )?;
        canvas.draw(&circle, graphics::DrawParam::default());


        let rect = graphics::Mesh::new_polygon(
            ctx,
            graphics::DrawMode::Stroke(StrokeOptions::DEFAULT),
            &[
                vec_to_render(&Vec3::new(0.0, 0.0, 300.0)),
                vec_to_render(&Vec3::new(300.0, 0.0, 300.0)),
                vec_to_render(&Vec3::new(300.0, 300.0, 300.0)),
                vec_to_render(&Vec3::new(0.0, 300.0, 300.0)),
            ],
            graphics::Color::new(0.0, 0.0, 0.0, 1.0),
        )?;
        canvas.draw(&rect, graphics::DrawParam::default());
        let rect = graphics::Mesh::new_polygon(
            ctx,
            graphics::DrawMode::Stroke(StrokeOptions::DEFAULT),
            &[
                vec_to_render(&Vec3::new(0.0, 300.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 300.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 300.0, 300.0)),
                vec_to_render(&Vec3::new(0.0, 300.0, 300.0)),
            ],
            graphics::Color::new(0.0, 0.0, 0.0, 1.0),
        )?;
        canvas.draw(&rect, graphics::DrawParam::default());
        let rect = graphics::Mesh::new_polygon(
            ctx,
            graphics::DrawMode::Stroke(StrokeOptions::DEFAULT),
            &[
                vec_to_render(&Vec3::new(300.0, 0.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 300.0, 0.0)),
                vec_to_render(&Vec3::new(300.0, 300.0, 300.0)),
                vec_to_render(&Vec3::new(300.0, 0.0, 300.0)),
            ],
            graphics::Color::new(0.0, 0.0, 0.0, 1.0),
        )?;
        canvas.draw(&rect, graphics::DrawParam::default());

        
        canvas.finish(ctx)?;
        Ok(())
    }
}

fn vec_to_render(v: &Vec3) -> Point2<f32> {
    let x = ZERO_PIVOT.x + UX.x*v.x + UY.x*v.y + UZ.x*v.z;
    let y = ZERO_PIVOT.y + UX.y*v.x + UY.y*v.y + UZ.y*v.z;
    Point2 { x, y }
}